package moon.core.instruction;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

import moon.core.classdef.LocalDec;

/** 
 * Instruction composes of several instructions. Pattern Design Composite.
 * 
 * @see moon.core.instruction.Instr
 * @author <a href="mailto:rmartico@ubu.es">Ra&uacute;l Marticorena</a>
 */
@SuppressWarnings("serial")
public abstract class CompoundInstr extends Instr implements Cloneable{
	
	/**
	 *  Set of instructions that compose this instruction.
     */    
    private List<Instr> instructions;
    
    /**
     * Local declarations with scope this compound instr.
     */
    private List<LocalDec> localDeclarations;
    
    /** 
     * Constructor.
     * 
     * @param line line
     * @param column column
     */
    public CompoundInstr(int line, int column) {
        super(line, column);        
        instructions = new ArrayList<Instr>();
        localDeclarations = new ArrayList<LocalDec>();
    }
    
    /** 
     * Adds a new instruction.
     * 
     * @param pInst instruction
     */    
    public void addInstruction(Instr pInst){
        instructions.add(pInst);
    }
    
    /**
     * Removes an instruction.
     * 
     * @param pInstr instruction
     */
    public void removeInstruction(Instr pInstr){
		ListIterator<Instr> list = this.getInstructions().listIterator();
		while(list.hasNext()){
			Instr instr = list.next();
			if (instr == pInstr){
					list.remove();
			}
		}
    }
    
    /** 
     * Gets the instructions in this instruction.
     * 
     * @return set of instructions
     * @see #setInstructions
     */    
    public List<Instr> getInstructions(){
        return instructions;
    }
    
    /** 
     * Sets the instructions in this instruction.
     * 
     * @param  list instruction set
     * @see #getInstructions
     */    
    public void setInstructions(List<Instr> list){
        instructions = list;
    } 
    
    /**
     * Textual representation.
     */
    public String toString(){
    	StringBuilder sb = new StringBuilder();
    	
    	for (Instr instr : this.getInstructions()){
    		sb.append(instr.toString());
    		sb.append(";\n");
    	}
    	return new String(sb);
    }

    /**
     * Clone.
     */
    public abstract Object clone();
    
    
    /**
     * Adds a local declaration.
     * 
     * @param localDec local declaration
     */
    public void add(LocalDec localDec){
    	this.localDeclarations.add(localDec);
    }
    
    /**
     * Removes a local declaration.
     * 
     * @param localDec local declaration
     */
    public void remove(LocalDec localDec){
    	this.localDeclarations.remove(localDec);
    }
    
    /**
     * Gets the local declarations.
     * 
     * @return list of local declarations
     */
    public List<LocalDec> getLocalDeclarations(){
    	return this.localDeclarations;
    }
    
    /**
     * Gets the first instruction.
     * 
     * @return first instruction
     */
    public Instr getFirstInstr(){
    	if (instructions.size()>0){
    		return this.instructions.get(0);
    	}
    	return null;
    }
    
    /**
     * Gets the last instruction.
     * 
     * @return first instruction
     */
    public Instr getLastInstr(){
    	if (instructions.size()>0){
    		return this.instructions.get(instructions.size()-1);
    	}
    	return null;
    }
} // CompoundInstr
